package cn.com.huzo.webapp.controller.tech;

import cn.com.huzo.model.entities.tech.MrpHeaderEntity;
import cn.com.huzo.model.entities.tech.MrpLinesAssortmentEntity;
import cn.com.huzo.model.entities.tech.MrpLinesResultEntity;
import huzofw.common.web.controller.BaseFormController;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import cn.com.huzo.service.tech.MrpHeaderManager;
import org.springframework.web.bind.annotation.PathVariable;
import cn.com.huzo.service.tech.MrpLinesAssortmentManager;
import org.apache.commons.collections4.MapUtils;
import cn.com.huzo.service.tech.MrpLinesResultManager;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

/**
 * 物料需求计划画面控制器
 *
 * @author 吴旭
 */
@Controller
public class MrpController extends BaseFormController {

    // <editor-fold defaultstate="collapsed" desc="属性">
    @Resource(name = "freemarkerConfig")
    private FreeMarkerConfigurer freemarkerConfig;

    @Resource(name = "MrpHeaderManager")
    private MrpHeaderManager _manager_header;

    @Resource(name = "MrpLinesAssortmentManager")
    private MrpLinesAssortmentManager _manager_lines_sssortment;

    @Resource(name = "MrpLinesResultManager")
    private MrpLinesResultManager _manager_lines_result;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="画面处理部分">
    /**
     * 跳转到提前组料单一览画面（主辅料）
     * <p>
     * @param request
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/main/list.html")
    public ModelAndView redirectMainMaterialListWnd(HttpServletRequest request) throws Exception {
        ModelAndView view = new ModelAndView();
        view.setViewName("tech.mrp_main.list.def");
        return view;
    }

    /**
     * 跳转到定版调达表一览画面（主辅料）
     * <p>
     * @param request
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/main_final/list.html")
    public ModelAndView redirectFinalMainMaterialListWnd(HttpServletRequest request) throws Exception {
        ModelAndView view = new ModelAndView();
        view.setViewName("tech.mrp_main_final.list.def");
        return view;
    }

    /**
     * 跳转到物料需求计划一览画面（副资材）
     * <p>
     * @param request
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/auxiliary/list.html")
    public ModelAndView redirectAuxiliaryMaterialListWnd(HttpServletRequest request) throws Exception {
        ModelAndView view = new ModelAndView();
        view.setViewName("tech.mrp_auxiliary.list.def");
        return view;
    }

    /**
     * 跳转提前组料单（主辅料）编辑画面
     * <p>
     * @param action 操作类别 1：增加 2：编辑
     * @param mrpId 物料需求计划标识
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/main/{action}/{mrpId}/edit.html")
    public ModelAndView redirectMainMaterialEditWnd(@PathVariable(value = "action") int action,
            @PathVariable(value = "mrpId") Long mrpId) throws Exception {
        ModelAndView view = new ModelAndView();
        // 为画面设置变量
        view.addObject("action", action);
        view.addObject("mrpId", mrpId);
        view.setViewName("tech.mrp_main.edit.def");
        return view;
    }

    /**
     * 跳转定版调达表（主辅料）编辑画面
     * <p>
     * @param action 操作类别 1：增加 2：编辑
     * @param mrpId 物料需求计划标识
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/main_final/{action}/{mrpId}/edit.html")
    public ModelAndView redirectFinalMainMaterialEditWnd(@PathVariable(value = "action") int action,
            @PathVariable(value = "mrpId") Long mrpId) throws Exception {
        ModelAndView view = new ModelAndView();
        // 为画面设置变量
        view.addObject("action", action);
        view.addObject("mrpId", mrpId);
        view.setViewName("tech.mrp_main_final.edit.def");
        return view;
    }

    /**
     * 跳转物料需求计划（副资材）编辑画面
     * <p>
     * @param action 操作类别 1：增加 2：编辑
     * @param mrpId 物料需求计划标识
     * @return
     * @throws java.lang.Exception
     */
    @RequestMapping("tech/mrp/auxiliary/{action}/{mrpId}/edit.html")
    public ModelAndView redirectAuxiliaryMaterialEditWnd(@PathVariable(value = "action") int action,
            @PathVariable(value = "mrpId") Long mrpId) throws Exception {
        ModelAndView view = new ModelAndView();
        // 为画面设置变量
        view.addObject("action", action);
        view.addObject("mrpId", mrpId);
        view.setViewName("tech.mrp_auxiliary.edit.def");
        return view;
    }

    /**
     * 搭配类型选择画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp/assortment_type/choice.html")
    public ModelAndView redirectChoiceAssortmentTypeWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("popup.tech.mrp_assortment_type.choice.def");
        return view;
    }

    /**
     * 搭配尺码选择画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp/assortment_size/choice.html")
    public ModelAndView redirectChoiceAssortmentSizeWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("popup.tech.mrp_assortment_size.choice.def");
        return view;
    }

    /**
     * 搭配目的地选择画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp/assortment_destination/choice.html")
    public ModelAndView redirectChoiceAssortmentDestinationWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("popup.tech.mrp_assortment_destination.choice.def");
        return view;
    }

    /**
     * 弹出物料需求计划选择画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp_for_po/choice.html")
    public ModelAndView redirectMrpChoiceWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("popup.tech.mrp_for_po.choice.def");
        return view;
    }

    /**
     * 提前组料单打印预览画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp_main/print.html")
    public ModelAndView redirectPrintPreviewWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("print.tech.mrp_main.print.def");
        return view;
    }

    /**
     * 定版调达表打印预览画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp_main_final/print.html")
    public ModelAndView redirectMainFinalPrintPreviewWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("print.tech.mrp_main_final.print.def");
        return view;
    }

    /**
     * 辅资材调达表打印预览画面
     * <p>
     * @return
     */
    @RequestMapping("tech/mrp_auxiliary/print.html")
    public ModelAndView redirectAuxiliaryPrintPreviewWnd() {
        ModelAndView view = new ModelAndView();
        view.setViewName("print.tech.mrp_auxiliary.print.def");
        return view;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="主表-数据处理部分">
    /**
     * 根据标识取得物料需求计划数据。
     *
     * @param criterion 物料需求计划标识及审核人（登录者）标识
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/fetchByKey.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> fetchByHeaderId(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.fetchByHeaderId(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getLong(criterion, "CurrentUserId"),
                MapUtils.getLong(criterion, "WorkFlowId"));
    }

    /**
     * 取得符合条件的物料需求计划。
     *
     * @param criterion 条件
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/fetchAll.html",
            method = RequestMethod.POST)
    public @ResponseBody
    List<MrpHeaderEntity> fetchAll(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.fetchAll(criterion);
    }

    /**
     * 根据条件取得物料需求计划信息分页数据。
     * <p>
     * @param criterion 检索条件
     * @return 物料需求计划信息分页数据
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/fetchForPage.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> fetchForPage(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.fetchForPage(criterion);
    }

    /**
     * 新增物料需求计划信息数据。
     * <p>
     * @param instance 要增加的物料需求计划信息对象。
     * @return 新增记录主键.
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/header/insert.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> insertHeader(@RequestBody final MrpHeaderEntity instance) throws Exception {
        return _manager_header.add(instance);
    }

    /**
     * 更新物料需求计划信息数据。
     * <p>
     * @param instance 要更新的物料需求计划信息对象。
     * @return 新增记录主键.
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/header/update.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Integer updateHeader(@RequestBody final MrpHeaderEntity instance) throws Exception {
        return _manager_header.update(instance);
    }

    /**
     * 删除物料需求计划信息数据。
     *
     * @param criterion 要删除的数据
     * @return 删除后的数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/header/delete.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> deleteHeader(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.delete(criterion);
    }

    /**
     * 审核物料需求计划数据。
     * <p>
     * @param criterion 要审核物料需求计划对象。
     * @return 影响行数.
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/check.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> check(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.doCheck(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getLong(criterion, "WorkFlowId"),
                MapUtils.getShort(criterion, "NodeOrder"),
                MapUtils.getLong(criterion, "CheckedBy"),
                MapUtils.getShort(criterion, "IsCheckCurrentNode")
        );
    }

    /**
     * 反审物料需求计划数据。
     * <p>
     * @param criterion 要审核物料需求计划对象。
     * @return 影响行数.
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/uncheck.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> unCheck(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.doUnCheck(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getLong(criterion, "WorkFlowId"),
                MapUtils.getShort(criterion, "NodeOrder"),
                MapUtils.getLong(criterion, "CheckedBy")
        );
    }

    /**
     * 设置采购完成状态。
     *
     * @param criterion 物料需求计划标识及审核人（登录者）标识
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/setPoOverFlag.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> setPoOverFlag(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.setPoOverFlag(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getLong(criterion, "CurrentUserId"),
                MapUtils.getLong(criterion, "WorkFlowId"),
                MapUtils.getBoolean(criterion, "PoOverFlag"));
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="明细-数据处理部分">
    /**
     * 根据设定的搭配类型计算物料需求。
     *
     * @param itemList 搭配计算参数(即搭配明细数据列表)
     * @return 计算后的物料需求。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/assortment/calculate.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> batchAssortCalculate(@RequestBody final List<MrpLinesAssortmentEntity> itemList) throws Exception {
        return _manager_lines_sssortment.batchAssort(itemList);
    }

    /**
     * 与单耗表进行同步。
     *
     * @param criterion 计算用参数
     * @return 同步后的搭配数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/assortment/syncbom.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> updateLinesForSyncBom(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_sssortment.updateLinesForSyncBom(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getLong(criterion, "BomHeaderId"),
                MapUtils.getLong(criterion, "MoHeaderId"),
                MapUtils.getString(criterion, "StyleNo"),
                MapUtils.getLong(criterion, "UpdatedBy"));
    }

    /**
     * 删除搭配明细数据。
     *
     * @param criterion 要删除的明细标识、主表id、删除的明细信息等
     * @return 删除后的搭配及需求明细。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/assortment/delete.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> deleteLines(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_sssortment.delete(criterion);
    }

    /**
     * 批量删除搭配明细数据。
     *
     * @param itemList 要删除的数据
     * @return 删除后的搭配及需求明细。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/assortment/batch_delete.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> batchDeleteLines(@RequestBody final List<MrpLinesAssortmentEntity> itemList) throws Exception {
        return _manager_lines_sssortment.batchDelete(itemList);
    }

    /**
     * 根据搭配类型取得物料需求明细。
     *
     * @param criterion 过滤条件
     * @return 物料需求明细
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/fetchByAssortmentType.html",
            method = RequestMethod.POST)
    public @ResponseBody
    List<MrpLinesResultEntity> fetchByAssortmentType(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_result.fetchByAssortmentType(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getShort(criterion, "AssortmentType"),
                MapUtils.getShort(criterion, "SortType"));
    }

    /**
     * 根据标识取得物料需求计划数据。
     *
     * @param headerId 物料需求计划标识
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/fetchByHeaderKey.html",
            method = RequestMethod.POST)
    public @ResponseBody
    List<MrpLinesResultEntity> fetchResultLinesByHeaderId(@RequestBody final Long headerId) throws Exception {
        return _manager_lines_result.fetchByHeaderId(headerId);
    }

    /**
     * 用于采购订单引入调达明细
     *
     * @param criterion 成品标识、调用来源
     * @return 物料需求计划明细数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/fetchForPage.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> fetchLinesForPage(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_result.fetchForPage(criterion);
    }

    /**
     * 保存物料需求计划明细数据。
     * <p>
     * @param criterion 主表ID、更新者、要保存的数据。
     * @return 影响行数.
     * @throws Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/batch_update.html",
            method = RequestMethod.POST)

    public @ResponseBody
    Map<String, Object> batchUpdateResultLines(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_result.batchUpdate(criterion);
    }

    /**
     * 重新计算物料需求信息（前提：单耗或者物料需求计划发生变化）。
     *
     * @param criterion 计算用参数
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/re_calculate.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> reCalculate(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_lines_result.reCalculate(
                MapUtils.getLong(criterion, "HeaderId"),
                MapUtils.getShort(criterion, "BillType"),
                MapUtils.getLong(criterion, "BomHeaderId"),
                MapUtils.getLong(criterion, "MoHeaderId"),
                MapUtils.getString(criterion, "StyleNo"),
                MapUtils.getLong(criterion, "UpdatedBy"));
    }

    /**
     * 仓库根据款号得到备料信息
     *
     * @param paramsMap 计算用参数
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/lines/result/fetchForStockOut.html",
            method = RequestMethod.POST)
    public @ResponseBody
    List<Map<String, Object>> fetchForStockOut(@RequestBody final Map<String, Object> paramsMap) throws Exception {
        return _manager_lines_result.fetchForStockOut(paramsMap);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="打印处理部分">
    /**
     * 打印预览。
     *
     * @param criterion 标识等
     * @return 物料需求计划数据。
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/fetchPrintPreviewData.html",
            method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> fetchPrintPreviewData(@RequestBody final Map<String, Object> criterion) throws Exception {
        return _manager_header.fetchPrintPreviewData(criterion);
    }

    /**
     * 导出生产指示书
     *
     * @param response 客户端响应
     * @param request 客户端请求
     * @throws java.lang.Exception
     */
    @RequestMapping(value = "tech/mrp/export_to_excel.html",
            method = RequestMethod.POST)
    public void exportDataWithMoFormatToExcel(HttpServletResponse response, HttpServletRequest request) throws Exception {
        long _headerId = Long.parseLong(request.getParameter("_ExportHeaderId").trim());
        long _moHeaderId = Long.parseLong(request.getParameter("_ExportMoHeaderId").trim());
        long _bomHeaderId = Long.parseLong(request.getParameter("_ExportBomHeaderId").trim());
        long _productId = Long.parseLong(request.getParameter("_ExportProductId").trim());

        Map<String, Object> data = _manager_header.fetchPrintDataWithMoFormat(_headerId, _moHeaderId, _productId, _bomHeaderId);

        String filename = "生产指示书(" + ((Map<String, Object>) data.get("ProductInfo")).get("contractno") + "-" + ((Map<String, Object>) data.get("ProductInfo")).get("styleno") + ").xls";

        try (OutputStream out = response.getOutputStream()) {
            response.reset();                                                   // 清空输出流
            response.setHeader("Content-disposition", "attachment; filename="
                    + new String(filename.getBytes("GB2312"), "ISO8859-1"));    // 设定输出文件头
            response.setContentType("application/msexcel");                     // 定义输出类型

            /**
             * **********创建工作簿************
             */
            parse("02_tech/生产指示书.ftl", data, out);
            out.flush();
        }
    }

    private void parse(String templateName, Map<String, Object> data, OutputStream out) throws IOException, TemplateException {
        try (OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {
            Configuration cfg = freemarkerConfig.getConfiguration();
            // 加载模板
            Template template = cfg.getTemplate(templateName, "utf-8");
            // 填充数据至Excel
            template.process(data, writer);
            writer.flush();
        }
    }
    // </editor-fold>
}
